﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XSTDZ.ERP.Application.DataContracts;
using AutoMapper;
using XSTDZ.ERP.Domain.Models;
using XSTDZ.ERP.Core.Repositories;
using XSTDZ.ERP.Core.Generator;

namespace XSTDZ.ERP.Application.Implements
{
    public class ProductCheckServiceImpl : ApplicationServiceBase, IProductCheckService
    {
        IRepository<ProductCheckBill> _productCheckRepository;
        IRepository<ProductCheckBillDetail> _productCheckDetailRepository;

        IRepository<ProfitAndLossBill> _profitAndLossBillRepository;
        IRepository<ProfitAndLossBillDetail> _profitAndLossBillDetailRepository;
        IRepository<Stock> _stockRepository;
        public ProductCheckServiceImpl(IRepositoryContext repositoryContext, IRepository<ProductCheckBill> productCheckRepository, IRepository<ProductCheckBillDetail> productCheckDetailRepository, IRepository<ProfitAndLossBill> profitAndLossBillRepository, IRepository<ProfitAndLossBillDetail> profitAndLossBillDetailRepository, IRepository<Stock> stockRepository)
            : base(repositoryContext)
        {
            this._productCheckRepository = productCheckRepository;
            this._productCheckDetailRepository = productCheckDetailRepository;

            this._profitAndLossBillRepository = profitAndLossBillRepository;
            this._profitAndLossBillDetailRepository = profitAndLossBillDetailRepository;

            this._stockRepository = stockRepository;
        }

        public Guid AddProductCheckBill(ProductCheckBillDto productCheckBillDto)
        {
            var productCheckBill = Mapper.Map<ProductCheckBillDto, ProductCheckBill>(productCheckBillDto);
            productCheckBill.InitProductCheck();
            this._productCheckRepository.Add(productCheckBill);
            this.Context.Commit();
            return productCheckBill.Id;
        }

        public Guid AddProductCheckBill(ProductCheckBillDto productCheckBillDto, IEnumerable<ProductCheckBillDetailDto> productCheckBillDetailDtos)
        {
            var productCheckBill = Mapper.Map<ProductCheckBillDto, ProductCheckBill>(productCheckBillDto);
            var productCheckBillDetails = Mapper.Map<IEnumerable<ProductCheckBillDetailDto>,IEnumerable< ProductCheckBillDetail>>(productCheckBillDetailDtos);
            //获取库存当前数量
            productCheckBillDetails.Each(d => {
                d.Amount = _stockRepository.GetByKey(d.StockID).StockCount;
            });

            productCheckBill.InitProductCheck().AddProductCheckDetails(productCheckBillDetails);
            this._productCheckRepository.Add(productCheckBill);
            this.Context.Commit();
            return productCheckBill.Id;
        }

        public Guid AddProductCheckBill(Guid productCheckBillId, IEnumerable<ProductCheckBillDetailDto> productCheckBillDetailDtos)
        {
            var productCheckBill = this._productCheckRepository.GetByKey(productCheckBillId);
            var productCheckBillDetails = Mapper.Map<IEnumerable<ProductCheckBillDetailDto>, IEnumerable<ProductCheckBillDetail>>(productCheckBillDetailDtos);
            //获取库存当前数量
            productCheckBillDetails.Each(d =>
            {
                d.Amount = _stockRepository.GetByKey(d.StockID).StockCount;
            });
            productCheckBill.InitProductCheck().AddProductCheckDetails(productCheckBillDetails);
            this._productCheckRepository.Add(productCheckBill);
            this.Context.Commit();
            return productCheckBill.Id;
        }

        public void UpdateProductCheckBill(ProductCheckBillDto productCheckBillDto)
        {
            var productCheckBill = Mapper.Map<ProductCheckBillDto, ProductCheckBill>(productCheckBillDto);
            this._productCheckRepository.Update(productCheckBill);
            this.Context.Commit();
        }

        public void UpdateProductCheckBill(Guid productCheckBillId, IEnumerable<ProductCheckBillDetailDto> productCheckBillDetailDtos)
        {
            var exists = this._productCheckRepository.Exists(d => d.Id == productCheckBillId);
            if(exists)
            {
                var productCheckBillDetails = Mapper.Map<IEnumerable<ProductCheckBillDetailDto>, IEnumerable<ProductCheckBillDetail>>(productCheckBillDetailDtos);
               // productCheckBillDetails.Each(d => { d.ProductCheckBillID = productCheckBillId; });
                productCheckBillDetails.Each(t => t.InitProductCheck());
                this._productCheckDetailRepository.Add(productCheckBillDetails);
                this.Context.Commit();
            }
        }

        public void UpdateProductCheckBill(ProductCheckBillDto productCheckBillDto, IEnumerable<ProductCheckBillDetailDto> productCheckBillDetailDtos)
        {
            var productCheckBill = this._productCheckRepository.GetByKey(productCheckBillDto.Id);
            productCheckBillDto.CreateTime = productCheckBill.CreateTime;
           var targetBill = Mapper.Map(productCheckBillDto,productCheckBill);
           
            //处理明细
            var productCheckBillDetails = Mapper.Map<IEnumerable<ProductCheckBillDetailDto>, IEnumerable<ProductCheckBillDetail>>(productCheckBillDetailDtos);

            var updateItems=new List<ProductCheckBillDetail>();
             var insertItems=new List<ProductCheckBillDetail>();
             var itemIds = productCheckBill.ProductCheckBillDetail.Select(d => d.Id).Cast<Guid>();

             productCheckBillDetails.Each(
                 pd =>
                 {
                     pd.Amount = _stockRepository.GetByKey(pd.StockID).StockCount; //获取库存当前数量
                     if (itemIds.Contains(pd.Id))
                     {
                         updateItems.Add(pd);
                     }
                     else
                     {
                         pd.ProductCheckBillID = productCheckBill.Id;
                         insertItems.Add(pd.InitProductCheck());
                     }
                 }
                 );

          
           if (updateItems.Count() != 0)
           {
               foreach (var p in targetBill.ProductCheckBillDetail)
               {
                   foreach (var m in updateItems)
                   {
                       if (m.Id == p.Id)
                       {
                           p.Deleted = 0;
                           p.StockID = m.StockID;
                           p.Amount = m.Amount;
                           p.EntityAmount = m.EntityAmount;
                           p.Remarks = m.Remarks;
                           break;
                       }
                   }
               }
              
               Mapper.Map(updateItems, targetBill.ProductCheckBillDetail);
           }
           if (insertItems.Count() != 0)
           {
               this._productCheckDetailRepository.Add(insertItems);
           }
           this._productCheckRepository.Update(targetBill);
           this.Context.Commit();
        }

        public void ConvertProductCheckBillDeleteState(Guid productCheckBillId)
        {
            var pbill = this._productCheckRepository.GetByKey(productCheckBillId);
            pbill.Deleted = 1;
            pbill.ProductCheckBillDetail.Each(d => { d.Deleted = 1; });
            this._productCheckRepository.Update(pbill);
            this.Context.Commit();
        }

        public void ConvertProductCheckBillDeleteState(Guid productCheckBillId, IEnumerable<Guid> productCheckBillDetailIds)
        {
            var pbill = this._productCheckRepository.GetByKey(productCheckBillId);
            pbill.ProductCheckBillDetail.Each(d => {
                if (productCheckBillDetailIds.Contains(d.Id))
                {
                    d.Deleted = 1;
                }
            });
            this._productCheckRepository.Update(pbill);
            this.Context.Commit();

        }
        public void Confirm(Guid billId, string profitAndLossNo)
        {
            var pbill = this._productCheckRepository.GetByKey(billId);
            if (pbill.BillState == 0)
            {
                pbill.BillState = 1;
                //不生成库存，只是生成损溢报告
                //  UpdateToStock(pbill);
                CreateProfitAndLoss(pbill, profitAndLossNo);
                _productCheckRepository.Update(pbill);
                this.Context.Commit();
            }
        }
        //生成损溢报告
        private void CreateProfitAndLoss(ProductCheckBill pcBill, string profitAndLossNo)
        {
            ProfitAndLossBillDto profitAndLossBillDto = new ProfitAndLossBillDto {
                ProfitAndLossNo = profitAndLossNo,
              StorehouseID = pcBill.StorehouseID,
              BillState=1,
              Remarks="生成",
              CreateID = pcBill.CreateID
            };//, IEnumerable<ProfitAndLossBillDetailDto> profitAndLossBillDetailDtos

            var profitAndLossBillDetailDtos = new List<ProfitAndLossBillDetailDto>();
            foreach (var item in pcBill.ProductCheckBillDetail)
            {
                if ((item.EntityAmount - item.Amount) != 0)
                {
                    profitAndLossBillDetailDtos.Add(new ProfitAndLossBillDetailDto
                    {
                        StockID = item.StockID,
                        Amount = item.EntityAmount - item.Amount,
                        Remarks = "生成"
                    });
                }
            }
            if (profitAndLossBillDetailDtos.Count > 0)
            {
                ProfitAndLossBillServiceImpl impl = new ProfitAndLossBillServiceImpl(this.Context, _profitAndLossBillRepository, _profitAndLossBillDetailRepository, _stockRepository);
                impl.AddProfitAndLoss(profitAndLossBillDto, profitAndLossBillDetailDtos);
            }
        }
        private void UpdateToStock(ProductCheckBill pbill)
        {
            var updateStocks = new List<Stock>();
            pbill.ProductCheckBillDetail.Each(d =>
            {

                updateStocks.Add(new Stock
                {
                    Id = d.StockID,
                    StockCount = d.EntityAmount - d.Amount
                });

            });
            if (updateStocks.Count() != 0)
            {
                StockServiceImpl stockServiceImpl = new StockServiceImpl(this.Context, this._stockRepository);
                stockServiceImpl.UpdateStockWithNoAdd(updateStocks);//更新库存
                this.Context.Commit();
            }
        }
        public void UpdateToStock(Guid productCheckBillId, IEnumerable<Guid> productCheckBillDetailIds)
        {
            var updateStocks = new List<Stock>();
            var pbill = this._productCheckRepository.GetByKey(productCheckBillId);
            pbill.ProductCheckBillDetail.Each(d =>
            {
                if (productCheckBillDetailIds.Contains(d.Id))
                {
                    updateStocks.Add(new Stock
                    {
                        Id = d.StockID,
                        StockCount = d.EntityAmount - d.Amount
                    });
                }
            });
            if (updateStocks.Count() != 0)
            {
                StockServiceImpl stockServiceImpl = new StockServiceImpl(this.Context, this._stockRepository);
                stockServiceImpl.UpdateStockWithNoAdd(updateStocks);//更新库存
                this.Context.Commit();
            }
        }
        public ProductCheckBillDto GetProductCheckBill(Guid productCheckBillId)
        {
            var productCheckBill = this._productCheckRepository.GetByKey(productCheckBillId);
            return Mapper.Map<ProductCheckBill, ProductCheckBillDto>(productCheckBill);
        }

        public IEnumerable<ProductCheckBillDto> GetProductCheckBills(int pageIndex, int pageSize)
        {
            var orderby = new OrderByParameter<ProductCheckBill>(m => m.CreateTime, SortOrder.Descending);
            var productCheckBills = this._productCheckRepository.GetAll(1, 100, new[] { orderby });
            return Mapper.Map<IEnumerable<ProductCheckBill>, IEnumerable<ProductCheckBillDto>>(productCheckBills);
        }

        public void AddProductCheckBillDetail(Guid productInBillId, ProductCheckBillDetailDto productCheckBillDetailDto)
        {
            throw new NotImplementedException();
        }

        public void UpdateProductCheckBillDetail(Guid productInBillId, IEnumerable<ProductCheckBillDetailDto> productCheckBillDetailDtos)
        {
            throw new NotImplementedException();
        }

        public ProductCheckBillDetailDto GetProductCheckBillDetail(Guid productCheckBillDetailId)
        {
            var productCheckBill = this._productCheckDetailRepository.GetByKey(productCheckBillDetailId);
            return Mapper.Map<ProductCheckBillDetail, ProductCheckBillDetailDto>(productCheckBill);
        }

        public IEnumerable<ProductCheckBillDetailDto> GetProductCheckBillDetails(Guid productCheckBillId)
        {
            var productCheckBills = this._productCheckDetailRepository.GetAll(d => d.ProductCheckBillID == productCheckBillId&&d.Deleted==0);
            return Mapper.Map<IEnumerable<ProductCheckBillDetail>, IEnumerable<ProductCheckBillDetailDto>>(productCheckBills);
        }


        public string GetMaxBillNo()
        {
            var orderby = new OrderByParameter<ProductCheckBill>(m => m.CreateTime, SortOrder.Descending);
            var billNo = this._productCheckRepository.GetAll(1, 1, new[] { orderby }).FirstOrDefault();
            return billNo==null?string.Empty :billNo.CheckNo;
        }
      
    }

}
